package com.example.shuiyin.controller;

import com.example.shuiyin.dto.ApiResponse;
import com.example.shuiyin.entity.User;
import com.example.shuiyin.exception.AppException;
import com.example.shuiyin.service.MinioStorageService;
import com.example.shuiyin.config.MinioConfig;
import com.example.shuiyin.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import io.minio.GetObjectArgs;
import io.minio.GetObjectResponse;
import io.minio.MinioClient;

@RestController
@RequestMapping("/api/avatars")
@RequiredArgsConstructor
@Slf4j
public class AvatarController {

    private final MinioStorageService minioStorageService;
    private final MinioConfig minioConfig;
    private final UserService userService;
    private final MinioClient minioClient;

    /**
     * 获取用户头像
     */
    @GetMapping("/{userId}/{filename:.+}")
    public ResponseEntity<?> getAvatar(@PathVariable Long userId, @PathVariable String filename) {
        log.info("获取用户[{}]头像: {}", userId, filename);
        
        try {
            // 检查文件是否存在
            String bucketName = minioConfig.getBucket();
            String objectName = "avatars/" + userId + "/" + filename;
            
            // 修复方法1：如果我们更新了 MinioStorageService 接口，保持这段代码不变
            boolean exists = minioStorageService.objectExists(bucketName, objectName);
            
            if (!exists) {
                return ResponseEntity.notFound().build();
            }
            
            // 获取文件
            InputStream inputStream = minioStorageService.getObject(bucketName, objectName);
            InputStreamResource resource = new InputStreamResource(inputStream);
            
            // 根据文件扩展名确定内容类型
            String contentType;
            if (filename.toLowerCase().endsWith(".jpg") || filename.toLowerCase().endsWith(".jpeg")) {
                contentType = "image/jpeg";
            } else if (filename.toLowerCase().endsWith(".png")) {
                contentType = "image/png";
            } else if (filename.toLowerCase().endsWith(".gif")) {
                contentType = "image/gif";
            } else {
                contentType = "application/octet-stream";
            }
            
            // 使用内联方式显示图片，而不是作为附件下载
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"")
                    .body(resource);
        } catch (IOException e) {
            log.error("获取头像失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("获取头像失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据token获取用户头像
     */
    @PostMapping("/token")
    public ResponseEntity<?> getAvatarByToken(@RequestBody Map<String, String> request) {
        try {
            String token = request.get("token");
            String userId = request.get("userId");
            String filename = request.get("filename");
            
            if (token == null || token.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                        .body("Token不能为空");
            }
            
            if (userId == null || userId.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                        .body("用户ID不能为空");
            }
            
            if (filename == null || filename.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                        .body("文件名不能为空");
            }
            
            // 检查文件是否存在
            String bucketName = minioConfig.getBucket();
            String objectName = "avatars/" + userId + "/" + filename;
            
            // 修复方法1：如果我们更新了 MinioStorageService 接口，保持这段代码不变
            boolean exists = minioStorageService.objectExists(bucketName, objectName);
            
            if (!exists) {
                return ResponseEntity.notFound().build();
            }
            
            // 获取文件
            InputStream inputStream = minioStorageService.getObject(bucketName, objectName);
            InputStreamResource resource = new InputStreamResource(inputStream);
            
            // 根据文件扩展名确定内容类型
            String contentType;
            if (filename.toLowerCase().endsWith(".jpg") || filename.toLowerCase().endsWith(".jpeg")) {
                contentType = "image/jpeg";
            } else if (filename.toLowerCase().endsWith(".png")) {
                contentType = "image/png";
            } else if (filename.toLowerCase().endsWith(".gif")) {
                contentType = "image/gif";
            } else {
                contentType = "application/octet-stream";
            }
            
            // 使用内联方式显示图片，而不是作为附件下载
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"")
                    .body(resource);
        } catch (IOException e) {
            log.error("获取头像失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("获取头像失败: " + e.getMessage());
        }
    }

    @GetMapping("/url/{userId}")
    public ResponseEntity<ApiResponse<String>> getAvatarUrl(@PathVariable Long userId) {
        try {
            // 替换为正确的方法名，例如 findById 或 getById
            User user = userService.findById(userId);  // 假设正确的方法名是 findById
            if (user == null || user.getAvatar() == null) {
                return ResponseEntity.ok(ApiResponse.error("用户不存在或没有头像"));
            }
            
            // 生成预签名URL
            String objectName = "avatars/" + userId + "/" + user.getAvatar();
            String presignedUrl = minioStorageService.generatePresignedUrl(minioConfig.getUserBucket(), objectName, 3600);
            
            return ResponseEntity.ok(ApiResponse.success("头像URL获取成功", presignedUrl));
        } catch (Exception e) {
            log.error("获取头像URL失败: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("获取头像URL失败: " + e.getMessage()));
        }
    }

    /**
     * 获取用户当前头像
     */
    @GetMapping("/{userId}/current")
    public ResponseEntity<?> getCurrentAvatar(@PathVariable Long userId) {
        log.info("获取用户[{}]当前头像", userId);
        
        try {
            // 替换为正确的方法名，例如 findById 或 getById
            User user = userService.findById(userId);  // 假设正确的方法名是 findById
            if (user == null || user.getAvatar() == null) {
                return ResponseEntity.notFound().build();
            }
            
            String filename = user.getAvatar();
            String bucketName = minioConfig.getUserBucket();
            String objectName = "avatars/" + userId + "/" + filename;
            
            // 检查文件是否存在
            boolean exists = minioStorageService.objectExists(bucketName, objectName);
            if (!exists) {
                return ResponseEntity.notFound().build();
            }
            
            // 获取文件并返回
            InputStream inputStream = minioStorageService.getObject(bucketName, objectName);
            InputStreamResource resource = new InputStreamResource(inputStream);
            
            // 确定内容类型
            String contentType = determineContentType(filename);
            
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"")
                    .body(resource);
        } catch (Exception e) {
            log.error("获取头像失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("获取头像失败: " + e.getMessage());
        }
    }

    // 辅助方法：根据文件名确定内容类型
    private String determineContentType(String filename) {
        if (filename.toLowerCase().endsWith(".jpg") || filename.toLowerCase().endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (filename.toLowerCase().endsWith(".png")) {
            return "image/png";
        } else if (filename.toLowerCase().endsWith(".gif")) {
            return "image/gif";
        } else {
            return "application/octet-stream";
        }
    }

    /**
     * 访问用户头像 - 从MinIO获取并代理返回
     */
    @GetMapping("/avatar/{userId}/{filename:.+}")
    public void getAvatar(
            @PathVariable Long userId,
            @PathVariable String filename,
            HttpServletResponse response) {
        
        String objectName = "avatar/" + userId + "/" + filename;
        log.debug("请求访问头像: {}", objectName);
        
        try {
            // 从MinIO获取文件
            GetObjectResponse object = minioClient.getObject(
                GetObjectArgs.builder()
                    .bucket(minioConfig.getBucket())
                    .object(objectName)
                    .build()
            );
            
            // 设置响应头
            response.setContentType(object.headers().get("Content-Type"));
            response.setHeader("Cache-Control", "max-age=86400"); // 缓存1天
            
            // 复制文件内容到响应输出流
            try (InputStream is = object) {
                IOUtils.copy(is, response.getOutputStream());
                response.flushBuffer();
            }
        } catch (Exception e) {
            log.error("获取头像失败: {}", e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            try {
                response.getWriter().write("头像不存在或无法访问");
            } catch (IOException ex) {
                log.error("写入响应失败", ex);
            }
        }
    }
} 